package test.work;

import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import utils.SmallTool;
import utils.StringUtil;
import utils.httpclient.HttpClient;
import utils.httpclient.HttpClientConfig;
import utils.httpclient.HttpClientUtil;
import utils.httpclient.UrlEntity;

import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.*;

/**
 * @Author: gcr
 * @Date: 2021/10/13 16:30
 */
public class DownpMImage226_250 {
    @SneakyThrows
    public static void main(String[] args) {

        String rootPath = DownpMImage.rootPath;

        // 思路 下载后创建新表进行保存pmid 和对应路径的集合 先删除为空的数据
        // 下载路径存在另一个字段里面 设置完成还是失败 下次下载直接略过
        String db = "pubmed.to_down";
        String sql = "select max(pmid) as count from " + db;
        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
        String fileName = stackTrace[0].getFileName();
        SmallTool.printMess("开始了+++" + fileName.replace(".java", ""));
        //DownpMImage1_1500.java
        int startStart = Integer.parseInt(fileName.replace("DownpMImage", "").replace(".java", "").split("_")[0]);
        int endEnd = Integer.parseInt(fileName.replace("DownpMImage", "").replace(".java", "").split("_")[1]);
        if (startStart != 1) {
            startStart = startStart * DownpMImage.breakSize;
        }
        endEnd = endEnd * DownpMImage.breakSize;
        SmallTool.printMess("开始id+" + startStart + "++end++" + endEnd);

        Db use = Db.use();
        Integer max = Integer.parseInt(use.queryString(sql));
        int breakSize = DownpMImage.breakSize;
        int page = max / breakSize + 1;
        SmallTool.printMess("最大值+++" + max);
        SmallTool.printMess("页码+++" + page);
        // 2021年10月16日09:39:30 还是太慢 直接给20个线程
        ExecutorService executors = Executors.newFixedThreadPool(DownpMImage.threadSize);
        // status 初始化数据 0 是原始值 1 是成功 2是失败
        for (int i = 1; i <= page; i++) {
            int start = breakSize * (i - 1) + 1;
            //目前跑了一千多万了
            if (start < startStart) {
                continue;
            }
            int end = breakSize * i;
            if (end > endEnd) {
                continue;
            }
            String querySql = "select * from " + db + " where pmid between " + start + " and " + end + " and status = 0";
            List<Entity> query = use.query(querySql);
            if (query.size() > 0) {
                SmallTool.printMess("pmid开始页码+" + i + "+++" + start + "++++end+++" + end);
            }
            for (Entity entity : query) {
                executors.submit(() -> {
                    Integer pmid = entity.getInt("pmid");
                    String figure = entity.getStr("figure");
                    if (StringUtils.isNotEmpty(figure) && !figure.equals("[]")) {
                        JSONArray strings = JSONArray.parseArray(figure);
                        List<String> urls = new LinkedList<>();
                        for (Object string : strings) {
                            JSONObject sin = (JSONObject) string;
                            Set<String> strings1 = sin.keySet();
                            String url = "";
                            for (String s : strings1) {
                                url = s;
                            }
                            // 进行下载
                            urls.add(url);
                        }
                        // 预处理位置 进行分组放下
                        String folderNameFront = pmid / 50000 + 1 + "";
                        String folderNameLast = pmid / 50000 + 2 + "";
                        String newPath = rootPath + folderNameFront + "-" + folderNameLast + "\\" + pmid + "\\";
                        Map<String, Object> stringObjectMap = DownImage(urls, newPath);
                        if (stringObjectMap.get("status").equals("success")) {
                            entity.set("status", 1);
                            entity.set("path", JSON.toJSONString(stringObjectMap.get("data")));
                            Entity param = new Entity();
                            param.setTableName(db);
                            param.set("pmid", pmid);
                            try {
                                use.update(entity, param);
                            } catch (SQLException throwables) {
                                throwables.printStackTrace();
                            }
                        } else {
                            entity.set("status", 2);
                            Entity param = new Entity();
                            param.setTableName(db);
                            param.set("pmid", pmid);
                            try {
                                use.update(entity, param);
                            } catch (SQLException throwables) {
                                throwables.printStackTrace();
                            }
                        }
                    } else {
                        entity.set("status", 1);
                        Entity param = new Entity();
                        param.setTableName(db);
                        param.set("pmid", pmid);
                        try {
                            use.update(entity, param);
                        } catch (SQLException throwables) {
                            throwables.printStackTrace();
                        }
                    }

                });
            }


        }
        executors.shutdown();
        while (true) {
            if (executors.isTerminated()) {
                SmallTool.printMess(fileName + "結束了");
                break;
            } else {

                Thread.sleep(1200);

            }
        }


    }


    @SneakyThrows
    public static Map<String, Object> DownImage(List<String> url, String path) {
        ExecutorService executorService = Executors.newFixedThreadPool(UrlEntity.coreThread);
        List<Future<Map<String, Object>>> taskRes = new LinkedList<>();
        Map<String, Object> resMap = new HashMap<>();
        for (int i = 0; i < url.size(); i++) {
            DoDown task = new DoDown(url.get(i), path);
            FutureTask futureTask = new FutureTask<>(task);
            taskRes.add(futureTask);
            executorService.submit(futureTask);
        }
        executorService.shutdown();
        while (true) {
            if (executorService.isTerminated()) {

                break;
            } else {
                Thread.sleep(1200);

            }
        }
        List<Map<String, Object>> resList = new LinkedList<>();
        for (Future<Map<String, Object>> taskRe : taskRes) {
            resList.add(taskRe.get());
        }
        String res = "success";
        List<String> resPath = new ArrayList<>();
        T:
        for (Map<String, Object> s : resList) {
            Set<String> strings = s.keySet();
            for (String string : strings) {
                resPath.add(s.get(string).toString());
                if (string.equals("faild")) {
                    res = "faild";
                    break T;
                }
            }
        }
        resMap.put("status", res);
        SmallTool.printMess("当前url全部下载结果+" + res);
        ;
        resMap.put("data", resPath);
        return resMap;
    }

    static class DoDown implements Callable {

        public Map<String, Object> resMap = new HashMap<>();
        private String url;
        private String path;

        public DoDown(String url, String path) {
            this.url = url;
            this.path = path;
        }

        @Override
        public Object call() {
            String fileName = StringUtil.getFileName(url);
            String res = "success";
            try {
                HttpClientConfig config = HttpClientUtil.getSearConfig(url, "", "", true);
                config.setProxy(false);
                config.setDirPath(path);
                config.setFilePath(fileName);
                HttpClient.getDownImage(config);
            } catch (Exception e) {
                res = "faild";
            }
            resMap.put(res, path + fileName);
            return resMap;
        }
    }


}
